﻿using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Linq;
using System;

namespace AudioCore.Common
{
    public static class ImageProcessing
    {
        public static void ResizeFromFile(string inFile, string outFile, Size outSize)
        {
            // Read image
            Image img = Image.FromFile(inFile);
            // Resize
            Rectangle r;
            Image outImage = ResizeToCanvas(img, outSize.Width, outSize.Height, out r);
            // Save image
            SaveAsJpeg(outImage, outFile, 100L);
        }

        public static Image ResizeImage(Image img, Size outSize)
        {
            try
            {
                Rectangle r;
                Image outImage = ResizeToCanvas(img, outSize.Width, outSize.Height, out r);
                return outImage;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        private static ImageCodecInfo GetEncoder(ImageFormat format)
        {
            return ImageCodecInfo.GetImageDecoders().SingleOrDefault(c => c.FormatID == format.Guid);
        }

        public static void SaveAsJpeg(this Image Img, string FileName, long Quality)
        {
            ImageCodecInfo jgpEncoder = GetEncoder(ImageFormat.Jpeg);
            Encoder QualityEncoder = Encoder.Quality;

            using (EncoderParameters EP = new EncoderParameters(1))
            {
                using (EncoderParameter QualityEncoderParameter = new EncoderParameter(QualityEncoder, Quality))
                {
                    EP.Param[0] = QualityEncoderParameter;
                    Img.Save(FileName, jgpEncoder, EP);
                }
            }
        }

        private static void SaveAsGif(this Image Img, string FileName, long Quality)
        {
            ImageCodecInfo gifEncoder = GetEncoder(ImageFormat.Gif);
            Encoder QualityEncoder = Encoder.Quality;

            using (EncoderParameters EP = new EncoderParameters(1))
            {
                using (EncoderParameter QualityEncoderParameter = new EncoderParameter(QualityEncoder, Quality))
                {
                    EP.Param[0] = QualityEncoderParameter;
                    Img.Save(FileName, gifEncoder, EP);
                }
            }
        }

        private static Image Resize(this Image Img, int Width, int Height)
        {
            return Img.Resize(Width, Height, InterpolationMode.HighQualityBicubic);
        }

        private static Image Resize(this Image Img, int Width, int Height, InterpolationMode InterpolationMode)
        {
            Image CropedImage = new Bitmap(Width, Height);
            using (Graphics G = Graphics.FromImage(CropedImage))
            {
                G.SmoothingMode = SmoothingMode.HighQuality;
                G.InterpolationMode = InterpolationMode;
                G.PixelOffsetMode = PixelOffsetMode.HighQuality;
                G.DrawImage(Img, 0, 0, Width, Height);
            }

            return CropedImage;
        }

        private static Rectangle EnsureAspectRatio(this Image Image, int Width, int Height)
        {
            float AspectRatio = Width / (float)Height;
            float CalculatedWidth = Image.Width, CalculatedHeight = Image.Height;

            if (Image.Width >= Image.Height)
            {
                if (Width > Height)
                {
                    CalculatedHeight = Image.Width / AspectRatio;
                    if (CalculatedHeight > Image.Height)
                    {
                        CalculatedHeight = Image.Height;
                        CalculatedWidth = CalculatedHeight * AspectRatio;
                    }
                }
                else
                {
                    CalculatedWidth = Image.Height * AspectRatio;
                    if (CalculatedWidth > Image.Width)
                    {
                        CalculatedWidth = Image.Width;
                        CalculatedHeight = CalculatedWidth / AspectRatio;
                    }
                }
            }
            else
            {
                if (Width < Height)
                {
                    CalculatedHeight = Image.Width / AspectRatio;
                    if (CalculatedHeight > Image.Height)
                    {
                        CalculatedHeight = Image.Height;
                        CalculatedWidth = CalculatedHeight * AspectRatio;
                    }
                }
                else
                {
                    CalculatedWidth = Image.Height * AspectRatio;
                    if (CalculatedWidth > Image.Width)
                    {
                        CalculatedWidth = Image.Width;
                        CalculatedHeight = CalculatedWidth / AspectRatio;
                    }
                }
            }
            return Rectangle.Ceiling(new RectangleF((Image.Width - CalculatedWidth) / 2, (Image.Height - CalculatedHeight) / 2, CalculatedWidth, CalculatedHeight));
        }

        private static Image ResizeToCanvas(this Image Img, int Width, int Height, out Rectangle CropRectangle)
        {
            return Img.ResizeToCanvas(Width, Height, InterpolationMode.HighQualityBicubic, out CropRectangle);
        }

        private static Image ResizeToCanvas(this Image Img, int Width, int Height, InterpolationMode InterpolationMode, out Rectangle CropRectangle)
        {
            CropRectangle = EnsureAspectRatio(Img, Width, Height);
            Image CropedImage = new Bitmap(Width, Height);

            using (Graphics G = Graphics.FromImage(CropedImage))
            {
                G.SmoothingMode = SmoothingMode.HighQuality;
                G.InterpolationMode = InterpolationMode;
                G.PixelOffsetMode = PixelOffsetMode.HighQuality;
                G.DrawImage(Img, new Rectangle(0, 0, Width, Height), CropRectangle, GraphicsUnit.Pixel);
            }

            return CropedImage;
        }

        private static Image ResizeToCanvas(this Image Img, int Width, int Height, RectangleF CR)
        {
            return Img.ResizeToCanvas(Width, Height, InterpolationMode.HighQualityBicubic, CR);
        }

        private static Image ResizeToCanvas(this Image Img, int Width, int Height, InterpolationMode InterpolationMode, RectangleF CR)
        {
            Image CropedImage = new Bitmap(Width, Height);
            using (Graphics G = Graphics.FromImage(CropedImage))
            {
                G.SmoothingMode = SmoothingMode.HighQuality;
                G.InterpolationMode = InterpolationMode;
                G.PixelOffsetMode = PixelOffsetMode.HighQuality;
                G.DrawImage(Img, new Rectangle(0, 0, Width, Height), CR, GraphicsUnit.Pixel);
            }

            return CropedImage;
        }
    }
}